<?php
/**
 * @Created by PhpStorm
 * @User    : 清风醉
 * @Date    : 2020/7/13 3:30 下午
 * @如果有bug，那肯定不是我的锅
 */

namespace Jooau\Base\Exception\Handler;

use Jooau\Base\Constants\ResponseCode;
use Jooau\Base\Exception\AdminAuthValidException;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Psr\Http\Message\ResponseInterface;
use Qbhy\HyperfAuth\Exception\UnauthorizedException;
use Qbhy\SimpleJwt\Exceptions\InvalidTokenException;
use Qbhy\SimpleJwt\Exceptions\SignatureException;
use Qbhy\SimpleJwt\Exceptions\TokenBlacklistException;
use Qbhy\SimpleJwt\Exceptions\TokenExpiredException;
use Qbhy\SimpleJwt\Exceptions\TokenNotActiveException;
use Qbhy\SimpleJwt\Exceptions\TokenProviderException;
use Qbhy\SimpleJwt\Exceptions\TokenRefreshExpiredException;
use Throwable;

class AdminAuthExceptionHandler extends ExceptionHandler
{

    public function handle(Throwable $throwable, ResponseInterface $response)
    {
        // TODO: Implement handle() method.
        if ($throwable instanceof AdminAuthValidException
            || $throwable instanceof UnauthorizedException
            || $throwable instanceof InvalidTokenException
            || $throwable instanceof SignatureException
            || $throwable instanceof TokenBlacklistException
            || $throwable instanceof TokenExpiredException
            || $throwable instanceof TokenNotActiveException
            || $throwable instanceof TokenProviderException
            || $throwable instanceof TokenRefreshExpiredException
        ) {
            $body = $throwable->getMessage();
            // 阻止异常冒泡
            $this->stopPropagation();
            $code = [
                    InvalidTokenException::class        => ResponseCode::TOKEN_INVALID,
                    SignatureException::class           => ResponseCode::TOKEN_SIGNATURE,
                    TokenBlacklistException::class      => ResponseCode::TOKEN_BLACKLIST,
                    TokenExpiredException::class        => ResponseCode::TOKEN_EXPIRED,
                    TokenNotActiveException::class      => ResponseCode::TOKEN_NOT_ACTIVE,
                    TokenProviderException::class       => ResponseCode::TOKEN_PROVIDER,
                    TokenRefreshExpiredException::class => ResponseCode::TOKEN_REFRESH_EXPIRED,
                ][$throwable->getPrevious() ? get_class($throwable->getPrevious()) : null] ??
                $throwable->getCode();
            return $response
                ->withStatus($throwable->getCode())
                ->withAddedHeader('content-type', 'application/json')
                ->withBody(new SwooleStream(failed("Authorization验证失败：" . $body, [],
                    $code)));
        }
        // 交给下一个异常处理器
        return $response;
    }

    public function isValid(Throwable $throwable): bool
    {
        // TODO: Implement isValid() method.
        if ($throwable instanceof AdminAuthValidException
            || $throwable instanceof UnauthorizedException
            || $throwable instanceof InvalidTokenException
            || $throwable instanceof SignatureException
            || $throwable instanceof TokenBlacklistException
            || $throwable instanceof TokenExpiredException
            || $throwable instanceof TokenNotActiveException
            || $throwable instanceof TokenProviderException
            || $throwable instanceof TokenRefreshExpiredException
        ) {
            return true;
        }
        return false;
    }
}